package io.cici.cc.mybatis.lite.binding;


import io.cici.cc.mybatis.lite.session.Session;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class MapperRegistry {

    private final Map<Class<?>, MapperProxyFactory<?>> map = new ConcurrentHashMap<>();

    public MapperRegistry() {
    }

    public <T> T getMapper(Class<T> type, Session session) {
        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) map.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        }
        try {
            return mapperProxyFactory.newInstance(session);
        } catch (Exception e) {
            throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
    }

    public <T> boolean hasMapper(Class<T> type) {
        return map.containsKey(type);
    }

    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) {
            if (hasMapper(type)) {
                throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
            }

            map.put(type, new MapperProxyFactory<>(type));


        }
    }

    public Collection<Class<?>> getMappers() {
        return Collections.unmodifiableCollection(map.keySet());
    }


    public void addMappers() {

        Set<Class<? extends Class<?>>> mapperSet = null;
        for (Class<?> mapperClass : mapperSet) {
            addMapper(mapperClass);
        }
    }

}
